package com.daikun.common.enums;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.daikun.common.exception.BizException;
import com.daikun.common.iface.SecurityConfigIface;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * 加解密枚举
 * @author earl created 2025-05-20
 * @version init 0.0.1
 */
@Slf4j
@Getter
@RequiredArgsConstructor
public enum SecurityEnum implements SecurityConfigIface {
    ENCRYPT("数据加密，不会存库", true) {
        public Pair<String, String> createParam(List<String> data, SecurityTypeEnum item, String uuid) {
            if (CollUtil.isEmpty(data) || item == null || StrUtil.isBlank(uuid)) {
                return null;
            }
            if (data.size() == 1 && item.getEncCheck().apply(data.get(0))) {
                return null;
            }
            if (data.size() >= MAX_LIMIT) {
                throw new BizException(BaseResultEnum.SECURITY_ENC_LIMIT);
            }
            JSONObject param = new JSONObject();
            param.set("encryptType", item.getCode());
            param.set("plainValueList", data);
            param.set("sysId", APPLICATION_NAME);
            param.set("requestTime", System.currentTimeMillis());
            return Pair.of("/api/v1/getEncryptKeyList", param.toString());
        }
    },

    DEEP_ENCRYPT("数据加密，会存库，需要场景 id", true) {
        public Pair<String, String> createParam(List<String> data, SecurityTypeEnum item, String uuid) {
            if (CollUtil.isEmpty(data) || item == null || StrUtil.isBlank(uuid)) {
                return null;
            }
            if (data.size() >= MAX_LIMIT) {
                throw new BizException(BaseResultEnum.SECURITY_ENC_LIMIT);
            }
            JSONObject param = JSONUtil.createObj().set("userId", uuid).set("encryptType", item.getCode()).set("sysId", APPLICATION_NAME)
                    .set("sceneId", getSceneId(data, isFlag(), item)).set("requestTime", System.currentTimeMillis());
            if (data.size() == 1) {
                if (item.getEncCheck().apply(data.get(0))) {
                    return null;
                }
                param.set("plainValue", data.get(0));
                return Pair.of("/api/v1/encrypt", param.toString());
            }
            param.set("plainValueList", data);
            return Pair.of("/api/v1/batchEncrypt", param.toString());
        }
    },

    DECRYPT("数据解密，需要场景 id", false) {
        public Pair<String, String> createParam(List<String> data, SecurityTypeEnum item, String uuid) {
            if (CollUtil.isEmpty(data) || item == null || StrUtil.isBlank(uuid)) {
                return null;
            }
            if (data.size() >= MAX_LIMIT) {
                throw new BizException(BaseResultEnum.SECURITY_DEC_LIMIT);
            }
            JSONObject param = JSONUtil.createObj().set("userId", uuid).set("encryptType", item.getCode()).set("sysId", APPLICATION_NAME)
                    .set("sceneId", getSceneId(data, isFlag(), item)).set("requestTime", System.currentTimeMillis());
            if (data.size() == 1) {
                if (item.getDecCheck().apply(data.get(0))) {
                    return null;
                }
                param.set("encryptKey", data.get(0));
                return Pair.of("/api/v1/decrypt", param.toString());
            }
            param.set("encryptKeyList", data);
            return Pair.of("/api/v1/batchDecrypt", param.toString());
        }
    },
    ;

    private final String desc;
    private final boolean flag;
    // 加解密单次最大个数限制
    private static final int MAX_LIMIT = 2000;

    static String getSceneId(List<String> data, boolean flag, SecurityTypeEnum item) {
        String sceneId;
        if (CollUtil.isEmpty(data))
            throw new BizException(BaseResultEnum.SECURITY_FAIL_05);
        if (flag) {
            sceneId = (data.size() == 1) ? item.getSingleEnc().get() : item.getBatchEnc().get();
        } else {
            sceneId = (data.size() == 1) ? item.getSingleDec().get() : item.getBatchDec().get();
        }
        return sceneId;
    }

    public abstract Pair<String, String> createParam(List<String> paramList, SecurityTypeEnum paramSecurityTypeEnum, String paramString);
}

